package com.taoist_awei.blog.api;

import com.fasterxml.jackson.annotation.JsonProperty;
import com.taoist_awei.blog.core.*;
import com.taoist_awei.blog.exception.InvalidRequestException;
import com.taoist_awei.blog.exception.ResourceNotFoundException;
import com.taoist_awei.blog.exception.UnKnownException;
import lombok.Data;
import org.apache.commons.codec.binary.Base64;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.ResponseEntity;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.*;
import javax.validation.Valid;
import javax.validation.constraints.NotEmpty;
import javax.validation.constraints.NotNull;
import java.util.*;

@RestController
@RequestMapping("/article")
public class ArticleApi {
    private final ArticleRepository articleRepository;
    private final ArticleService articleService;
    private final ClassifyRepository classifyRepository;
    private final IDService idService;
    @Value("${default.classify.id}")
    private String defaultClassifyId;

    @Autowired
    public ArticleApi(ArticleRepository articleRepository,
                      ArticleService articleService,
                      @Qualifier("defaultIDService") IDService idService,
                      ClassifyRepository classifyRepository) {
        this.articleRepository = articleRepository;
        this.articleService = articleService;
        this.idService = idService;
        this.classifyRepository = classifyRepository;
    }

    @PostMapping("/list")
    public ResponseEntity<?> getArticleList(@RequestBody @Valid ListParam listParam,
                                            BindingResult bindingResult) {
        if (bindingResult.hasErrors()) {
            throw new InvalidRequestException(bindingResult);
        }

        Optional<List<ArticleEntity>> optional =
                articleRepository.getArticleList(listParam.getPage(), listParam.getSize(), ArticleStatus.PUBLISH);
        if (optional.isPresent()) {
            List<ArticleEntity> articleEntityList = optional.get();
            for (ArticleEntity entity : articleEntityList) {
                entity.setContent(null);
                entity.setStatus(null);
            }
            HttpResult result = new HttpResult.HttpResultBuilder().ok(optional.get());
            return ResponseEntity.ok(result);
        } else {
            throw new UnKnownException();
        }
    }

    @GetMapping(value = "/{articleId}")
    public ResponseEntity<?> getArticle(@PathVariable(value = "articleId") String articleId) {
        Optional<ArticleEntity> optional = articleRepository.findArticleById(articleId);
        if (optional.isPresent()) {
            Base64 base64 = new Base64();
            ArticleEntity articleEntity = optional.get();
            if (articleEntity.getStatus().equals(ArticleStatus.DRAFT)) {
                throw new ResourceNotFoundException();
            }
            articleEntity.setContent(base64.encodeAsString(articleEntity.getContent().getBytes()));
            HttpResult result = new HttpResult.HttpResultBuilder().ok(articleEntity);
            return ResponseEntity.ok(result);
        } else {
            throw new ResourceNotFoundException();
        }
    }

    @PostMapping(value = "/publish")
    public ResponseEntity<?> publishArticle(@RequestBody @Valid PublishParam param,
                                            BindingResult bindingResult) {
        if (bindingResult.hasErrors()) {
            throw new InvalidRequestException(bindingResult);
        }
        Optional<ArticleEntity> optional = articleRepository.findArticleById(param.getArticleId());
        if (optional.isPresent()) {
            articleRepository.publish(optional.get().getArticleId());
            HttpResult result = new HttpResult.HttpResultBuilder()
                    .message("发布成功")
                    .statusCode(200)
                    .build();
            return ResponseEntity.ok(result);
        } else {
            throw new ResourceNotFoundException();
        }
    }

    @PostMapping(value = "/save")
    public ResponseEntity<?> saveArticle(@RequestBody @Valid ArticleParam param,
                                         BindingResult bindingResult) {
        if (bindingResult.hasErrors()) {
            throw new InvalidRequestException(bindingResult);
        }
        String summary = articleService.getSummary(param.getContent());
        Integer readTime = articleService.getReadTime(param.getContent());
        Integer words = articleService.getWords(param.getContent());
        String articleId = idService.getID();
        String classifyId = null;
        if (param.getClassifyId() == null || param.getClassifyId().equals("")) {
            classifyId = defaultClassifyId;
        } else {
            classifyId = param.getClassifyId();
        }
        Optional<ClassifyEntity> optional = this.classifyRepository.getClassifyById(classifyId);
        if (optional.isPresent()) {
            ArticleEntity entity = new ArticleEntity (
                    param.getTitle(),
                    param.getCreateTime(),
                    readTime,
                    param.getType(),
                    param.getContent(),
                    summary,
                    classifyId,
                    articleId,
                    param.getUpdateTime()
                    );
            entity.setWords(words);
            articleRepository.saveArticle(entity);
            HttpResult result = new HttpResult.HttpResultBuilder()
                    .message("保存成功")
                    .statusCode(200)
                    .build();

            return ResponseEntity.ok(result);
        } else {
            HttpResult result = new HttpResult.HttpResultBuilder()
                    .message("分类未找到")
                    .statusCode(400)
                    .build();
            throw new InvalidRequestException(result);
        }
    }

    @GetMapping("size")
    public ResponseEntity<?> getSize() {
        Optional<Integer> optional = this.articleRepository.getSize();
        if (optional.isPresent()) {
            HttpResult result = new HttpResult.HttpResultBuilder()
                    .message("请求成功")
                    .statusCode(200)
                    .data(new HashMap<String, Integer>() {{put("size", optional.get());}})
                    .build();
            return ResponseEntity.ok(result);
        } else {
            HttpResult result = new HttpResult.HttpResultBuilder()
                    .statusCode(500)
                    .message("服务器错误")
                    .build();
            return ResponseEntity.ok(result);
        }
    }
}

@Data
class ListParam {
    private Integer page;
    private Integer size;
}

@Data
class ArticleParam {
    @NotEmpty
    @JsonProperty(value = "title")
    private String title;
    @NotEmpty
    @JsonProperty(value = "content")
    private String content;
    @NotNull
    @JsonProperty(value = "createTime")
    private Date createTime;
    @NotEmpty
    @JsonProperty(value = "type")
    private String type;
    @NotNull
    @JsonProperty(value = "updateTime")
    private Date updateTime;
    @JsonProperty(value = "classifyId")
    private String classifyId;
}

@Data
class PublishParam {
    @NotEmpty
    @JsonProperty(value = "articleId")
    private String articleId;
}